package dao

import (
	"context"
	"errors"
	"github.com/go-sql-driver/mysql"
	"gorm.io/gorm"
)

var ErrUserDuplicate = errors.New("用户名冲突")

type IuserDao interface {
	Insert(ctx context.Context, user UserMode) error
	FindByUserName(ctx context.Context, username string) (UserMode, error)
	FindByID(ctx context.Context, id int64) (UserMode, error)
	FindByPhone(ctx context.Context, phone string) (UserMode, error)
}

type userDao struct {
	db *gorm.DB
}

func NewUserDao(db *gorm.DB) IuserDao {
	return &userDao{
		db: db,
	}
}

func (d *userDao) Insert(ctx context.Context, user UserMode) error {
	err := d.db.WithContext(ctx).Create(&user).Error
	// 一定会唯一索引冲突,通过这个避免check do something的并发问题
	if mysqlErr, ok := err.(*mysql.MySQLError); ok {
		const uniqueConflictsErrNo uint16 = 1062
		if mysqlErr.Number == uniqueConflictsErrNo {
			// 邮箱冲突 or 手机号码冲突
			return ErrUserDuplicate
		}
	}

	if err != nil {
		return err
	}
	return nil
}

func (d *userDao) FindByUserName(ctx context.Context, username string) (UserMode, error) {
	var data UserMode
	t := d.db.WithContext(ctx).Where("username=?", username).First(&data)
	if t.Error != nil {
		return data, t.Error
	}
	if t.RowsAffected >= 1 {
		return data, nil
	}
	return data, nil
}

func (d *userDao) FindByPhone(ctx context.Context, phone string) (UserMode, error) {
	var data UserMode
	t := d.db.WithContext(ctx).Where("phone=?", phone).First(&data)
	if t.Error != nil {
		return data, t.Error
	}
	if t.RowsAffected >= 1 {
		return data, nil
	}
	return data, nil
}

func (d *userDao) FindByID(ctx context.Context, id int64) (UserMode, error) {
	var user UserMode
	i := d.db.WithContext(ctx).Where("id =?", id).First(&user)
	if i.Error != nil {
		return user, i.Error
	}
	return user, nil
}
